{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c5148957",
   "metadata": {},
   "source": [
    "# Calendar features"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "6da3874d",
   "metadata": {},
   "source": [
    "Calendar features serve as key elements in time series forecasting. These features decompose date and time into basic units such as year, month, day, weekday, etc., allowing models to identify recurring patterns, understand seasonal variations, and identify trends. Calendar features can be used as [exogenous variables](../user_guides/exogenous-variables.html) because they are known for the period for which predictions are being made (the forecast horizon).\n",
    "\n",
    "**Dates and time in Pandas**\n",
    "\n",
    "Pandas provides a comprehensive set of capabilities tailored for handling time series data in various domains. Using the NumPy `datetime64` and `timedelta64` data types, Pandas combines a wide range of functionality from various Python libraries while introducing a wealth of novel tools to effectively manipulate time series data. This includes:\n",
    "\n",
    "+ Easily parse date and time data from multiple sources and formats.\n",
    "\n",
    "+ Generate sequences of fixed-frequency dates and time spans.\n",
    "\n",
    "+ Streamline the manipulation and conversion of date-time information, including time zones.\n",
    "\n",
    "+ Facilitate the resampling or conversion of time series data to specific frequencies.\n",
    "\n",
    "For an in-depth exploration of Pandas' comprehensive time series and date capabilities, please refer to this [resource](https://pandas.pydata.org/docs/user_guide/timeseries.html)."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "15dfe9dc",
   "metadata": {},
   "source": [
    "## Libraries and data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2c4c16c7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Libraries\n",
    "# ==============================================================================\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "from skforecast.datasets import fetch_dataset\n",
    "from feature_engine.datetime import DatetimeFeatures\n",
    "from feature_engine.creation import CyclicalFeatures"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "cc5647b4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">╭───────────────────────────────── <span style=\"font-weight: bold\">bike_sharing</span> ──────────────────────────────────╮\n",
       "│ <span style=\"font-weight: bold\">Description:</span>                                                                    │\n",
       "│ Hourly usage of the bike share system in the city of Washington D.C. during the │\n",
       "│ years 2011 and 2012. In addition to the number of users per hour, information   │\n",
       "│ about weather conditions and holidays is available.                             │\n",
       "│                                                                                 │\n",
       "│ <span style=\"font-weight: bold\">Source:</span>                                                                         │\n",
       "│ Fanaee-T,Hadi. (2013). Bike Sharing Dataset. UCI Machine Learning Repository.   │\n",
       "│ https://doi.org/10.24432/C5W894.                                                │\n",
       "│                                                                                 │\n",
       "│ <span style=\"font-weight: bold\">URL:</span>                                                                            │\n",
       "│ https://raw.githubusercontent.com/skforecast/skforecast-                        │\n",
       "│ datasets/main/data/bike_sharing_dataset_clean.csv                               │\n",
       "│                                                                                 │\n",
       "│ <span style=\"font-weight: bold\">Shape:</span> 17544 rows x 12 columns                                                  │\n",
       "╰─────────────────────────────────────────────────────────────────────────────────╯\n",
       "</pre>\n"
      ],
      "text/plain": [
       "╭───────────────────────────────── \u001b[1mbike_sharing\u001b[0m ──────────────────────────────────╮\n",
       "│ \u001b[1mDescription:\u001b[0m                                                                    │\n",
       "│ Hourly usage of the bike share system in the city of Washington D.C. during the │\n",
       "│ years 2011 and 2012. In addition to the number of users per hour, information   │\n",
       "│ about weather conditions and holidays is available.                             │\n",
       "│                                                                                 │\n",
       "│ \u001b[1mSource:\u001b[0m                                                                         │\n",
       "│ Fanaee-T,Hadi. (2013). Bike Sharing Dataset. UCI Machine Learning Repository.   │\n",
       "│ https://doi.org/10.24432/C5W894.                                                │\n",
       "│                                                                                 │\n",
       "│ \u001b[1mURL:\u001b[0m                                                                            │\n",
       "│ https://raw.githubusercontent.com/skforecast/skforecast-                        │\n",
       "│ datasets/main/data/bike_sharing_dataset_clean.csv                               │\n",
       "│                                                                                 │\n",
       "│ \u001b[1mShape:\u001b[0m 17544 rows x 12 columns                                                  │\n",
       "╰─────────────────────────────────────────────────────────────────────────────────╯\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date_time</th>\n",
       "      <th>users</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2011-01-01 00:00:00</td>\n",
       "      <td>16.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2011-01-01 01:00:00</td>\n",
       "      <td>40.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2011-01-01 02:00:00</td>\n",
       "      <td>32.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2011-01-01 03:00:00</td>\n",
       "      <td>13.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2011-01-01 04:00:00</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             date_time  users\n",
       "0  2011-01-01 00:00:00   16.0\n",
       "1  2011-01-01 01:00:00   40.0\n",
       "2  2011-01-01 02:00:00   32.0\n",
       "3  2011-01-01 03:00:00   13.0\n",
       "4  2011-01-01 04:00:00    1.0"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Downloading data\n",
    "# ==============================================================================\n",
    "data = fetch_dataset(name=\"bike_sharing\", raw=True)\n",
    "data = data[['date_time', 'users']]\n",
    "data.head()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c879c7a7",
   "metadata": {},
   "source": [
    "## Extract calendar features"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To take advantage of the date-time functionality offered by Pandas, the column of interest must be stored as `datetime`. Although not required, it is recommended to set it as an index for further integration with skforecast."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>users</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date_time</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2011-01-01 00:00:00</th>\n",
       "      <td>16.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 01:00:00</th>\n",
       "      <td>40.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 02:00:00</th>\n",
       "      <td>32.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 03:00:00</th>\n",
       "      <td>13.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 04:00:00</th>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                     users\n",
       "date_time                 \n",
       "2011-01-01 00:00:00   16.0\n",
       "2011-01-01 01:00:00   40.0\n",
       "2011-01-01 02:00:00   32.0\n",
       "2011-01-01 03:00:00   13.0\n",
       "2011-01-01 04:00:00    1.0"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Preprocess data\n",
    "# ==============================================================================\n",
    "data['date_time'] = pd.to_datetime(data['date_time'], format='%Y-%m-%d %H:%M:%S')\n",
    "data = data.set_index('date_time')\n",
    "data = data.asfreq('h')\n",
    "data = data.sort_index()\n",
    "data.head()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "42b58b7c",
   "metadata": {},
   "source": [
    "Next, several features are created from the date and time information: year, month, day of the week, and hour."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>users</th>\n",
       "      <th>year</th>\n",
       "      <th>month</th>\n",
       "      <th>day_of_week</th>\n",
       "      <th>hour</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date_time</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2011-01-01 00:00:00</th>\n",
       "      <td>16.0</td>\n",
       "      <td>2011</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 01:00:00</th>\n",
       "      <td>40.0</td>\n",
       "      <td>2011</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 02:00:00</th>\n",
       "      <td>32.0</td>\n",
       "      <td>2011</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 03:00:00</th>\n",
       "      <td>13.0</td>\n",
       "      <td>2011</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 04:00:00</th>\n",
       "      <td>1.0</td>\n",
       "      <td>2011</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                     users  year  month  day_of_week  hour\n",
       "date_time                                                 \n",
       "2011-01-01 00:00:00   16.0  2011      1            5     0\n",
       "2011-01-01 01:00:00   40.0  2011      1            5     1\n",
       "2011-01-01 02:00:00   32.0  2011      1            5     2\n",
       "2011-01-01 03:00:00   13.0  2011      1            5     3\n",
       "2011-01-01 04:00:00    1.0  2011      1            5     4"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create calendar features\n",
    "# ==============================================================================\n",
    "data['year'] = data.index.year\n",
    "data['month'] = data.index.month\n",
    "data['day_of_week'] = data.index.dayofweek\n",
    "data['hour'] = data.index.hour\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"admonition note\" name=\"html-admonition\" style=\"background: rgba(0,191,191,.1); padding-top: 0px; padding-bottom: 6px; border-radius: 8px; border-left: 8px solid #00bfa5; border-color: #00bfa5; padding-left: 10px; padding-right: 10px;\">\n",
    "\n",
    "<p class=\"title\">\n",
    "    <i style=\"font-size: 18px; color:#00bfa5;\"></i>\n",
    "    <b style=\"color: #00bfa5;\">&#128161 Tip</b>\n",
    "</p>\n",
    "\n",
    "Numerous calendar-related features can be generated, including day of the year, week of the year, hour of the day, and others. An easy approach to automate their extraction is to use the <code>DatetimeFeatures</code> transformer within the **Feature-engine** Python library. This class integrates seamlessly into the scikit-learn pipeline, making it compatible with skforecast as well. For a deeper understanding and detailed information, please refer to <a href=\"https://feature-engine.trainindata.com/en/latest/user_guide/datetime/DatetimeFeatures.html#datetime-features\">DatetimeFeatures</a>.\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>users</th>\n",
       "      <th>year</th>\n",
       "      <th>month</th>\n",
       "      <th>day_of_week</th>\n",
       "      <th>hour</th>\n",
       "      <th>week</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date_time</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2011-01-01 00:00:00</th>\n",
       "      <td>16.0</td>\n",
       "      <td>2011</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "      <td>52</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 01:00:00</th>\n",
       "      <td>40.0</td>\n",
       "      <td>2011</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "      <td>1</td>\n",
       "      <td>52</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 02:00:00</th>\n",
       "      <td>32.0</td>\n",
       "      <td>2011</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "      <td>2</td>\n",
       "      <td>52</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 03:00:00</th>\n",
       "      <td>13.0</td>\n",
       "      <td>2011</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "      <td>3</td>\n",
       "      <td>52</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 04:00:00</th>\n",
       "      <td>1.0</td>\n",
       "      <td>2011</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "      <td>4</td>\n",
       "      <td>52</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                     users  year  month  day_of_week  hour  week\n",
       "date_time                                                       \n",
       "2011-01-01 00:00:00   16.0  2011      1            5     0    52\n",
       "2011-01-01 01:00:00   40.0  2011      1            5     1    52\n",
       "2011-01-01 02:00:00   32.0  2011      1            5     2    52\n",
       "2011-01-01 03:00:00   13.0  2011      1            5     3    52\n",
       "2011-01-01 04:00:00    1.0  2011      1            5     4    52"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create calendar features with Feature-engine\n",
    "# ==============================================================================\n",
    "features_to_extract = ['month', 'week', 'day_of_week', 'hour']\n",
    "calendar_transformer = DatetimeFeatures(\n",
    "                           variables           = 'index',\n",
    "                           features_to_extract = features_to_extract,\n",
    "                           drop_original       = True,\n",
    "                       )\n",
    "\n",
    "calendar_features = calendar_transformer.fit_transform(data)\n",
    "calendar_features.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sunlight-Related Features"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sunlight often plays a key role in time series patterns. For example, a household's hourly electricity consumption may correlate significantly with whether it's nighttime, as more electricity is typically used for lighting during those hours. Understanding and incorporating sunlight-related characteristics into analyses can provide valuable insights into consumption patterns and behavioral trends. In addition, factors such as sunrise/sunset times, seasonal changes affecting daylight, and their influence on different data sets can provide deeper context and help predict consumption fluctuations. There are several Python libraries available for extracting sunrise and sunset times. Two of the most commonly used are `pvlib` and `astral`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "c66d6a4a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>sunrise_hour</th>\n",
       "      <th>sunset_hour</th>\n",
       "      <th>daylight_hours</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date_time</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2012-12-31 19:00:00</th>\n",
       "      <td>8</td>\n",
       "      <td>16</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-12-31 20:00:00</th>\n",
       "      <td>8</td>\n",
       "      <td>16</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-12-31 21:00:00</th>\n",
       "      <td>8</td>\n",
       "      <td>16</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-12-31 22:00:00</th>\n",
       "      <td>8</td>\n",
       "      <td>16</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-12-31 23:00:00</th>\n",
       "      <td>8</td>\n",
       "      <td>16</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                     sunrise_hour  sunset_hour  daylight_hours\n",
       "date_time                                                     \n",
       "2012-12-31 19:00:00             8           16               8\n",
       "2012-12-31 20:00:00             8           16               8\n",
       "2012-12-31 21:00:00             8           16               8\n",
       "2012-12-31 22:00:00             8           16               8\n",
       "2012-12-31 23:00:00             8           16               8"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Features based on the sunligth\n",
    "# ==============================================================================\n",
    "from astral.sun import sun\n",
    "from astral import LocationInfo\n",
    "\n",
    "location = LocationInfo(\"Washington, D.C.\", \"USA\")\n",
    "sunrise_hour = [sun(location.observer, date=date)['sunrise'] for date in data.index]\n",
    "sunset_hour = [sun(location.observer, date=date)['sunset'] for date in data.index]\n",
    "\n",
    "# Round to the nearest hour\n",
    "sunrise_hour = pd.Series(sunrise_hour, index=data.index).dt.round(\"h\").dt.hour\n",
    "sunset_hour = pd.Series(sunset_hour, index=data.index).dt.round(\"h\").dt.hour\n",
    "\n",
    "sun_light_features = pd.DataFrame({\n",
    "                         'sunrise_hour': sunrise_hour,\n",
    "                         'sunset_hour': sunset_hour}\n",
    "                     )\n",
    "sun_light_features['daylight_hours'] = sun_light_features['sunset_hour'] - sun_light_features['sunrise_hour']\n",
    "sun_light_features.tail()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cyclical encoding"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Certain aspects of the calendar, such as hours of the day or days of the week, behave in cycles. For example, the hours of a day range from 0 to 23. If interpreted as a continuous variable, the hour of 23:00 would be 23 units away from the hour of 00:00. However, this is not true because 23:00 is only one hour away from 00:00. The same is true for the months of the year, since December is only one month away from January. Using techniques such as trigonometric functions - sine and cosine transformations - makes it possible to represent cyclic patterns and avoid inconsistencies in data representation. This technique is called cyclic coding and can significantly improve the predictive power of models."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>users</th>\n",
       "      <th>year</th>\n",
       "      <th>month_sin</th>\n",
       "      <th>month_cos</th>\n",
       "      <th>week_sin</th>\n",
       "      <th>week_cos</th>\n",
       "      <th>day_of_week_sin</th>\n",
       "      <th>day_of_week_cos</th>\n",
       "      <th>hour_sin</th>\n",
       "      <th>hour_cos</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date_time</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2011-01-01 00:00:00</th>\n",
       "      <td>16.0</td>\n",
       "      <td>2011</td>\n",
       "      <td>0.5</td>\n",
       "      <td>0.866025</td>\n",
       "      <td>-2.449294e-16</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-0.974928</td>\n",
       "      <td>-0.222521</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 01:00:00</th>\n",
       "      <td>40.0</td>\n",
       "      <td>2011</td>\n",
       "      <td>0.5</td>\n",
       "      <td>0.866025</td>\n",
       "      <td>-2.449294e-16</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-0.974928</td>\n",
       "      <td>-0.222521</td>\n",
       "      <td>0.258819</td>\n",
       "      <td>0.965926</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2011-01-01 02:00:00</th>\n",
       "      <td>32.0</td>\n",
       "      <td>2011</td>\n",
       "      <td>0.5</td>\n",
       "      <td>0.866025</td>\n",
       "      <td>-2.449294e-16</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-0.974928</td>\n",
       "      <td>-0.222521</td>\n",
       "      <td>0.500000</td>\n",
       "      <td>0.866025</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                     users  year  month_sin  month_cos      week_sin  \\\n",
       "date_time                                                              \n",
       "2011-01-01 00:00:00   16.0  2011        0.5   0.866025 -2.449294e-16   \n",
       "2011-01-01 01:00:00   40.0  2011        0.5   0.866025 -2.449294e-16   \n",
       "2011-01-01 02:00:00   32.0  2011        0.5   0.866025 -2.449294e-16   \n",
       "\n",
       "                     week_cos  day_of_week_sin  day_of_week_cos  hour_sin  \\\n",
       "date_time                                                                   \n",
       "2011-01-01 00:00:00       1.0        -0.974928        -0.222521  0.000000   \n",
       "2011-01-01 01:00:00       1.0        -0.974928        -0.222521  0.258819   \n",
       "2011-01-01 02:00:00       1.0        -0.974928        -0.222521  0.500000   \n",
       "\n",
       "                     hour_cos  \n",
       "date_time                      \n",
       "2011-01-01 00:00:00  1.000000  \n",
       "2011-01-01 01:00:00  0.965926  \n",
       "2011-01-01 02:00:00  0.866025  "
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Cyclical encoding\n",
    "# ==============================================================================\n",
    "features_to_encode = [\n",
    "    \"month\",\n",
    "    \"week\",\n",
    "    \"day_of_week\",\n",
    "    \"hour\",\n",
    "]\n",
    "max_values = {\n",
    "    \"month\": 12,\n",
    "    \"week\": 52,\n",
    "    \"day_of_week\": 7,\n",
    "    \"hour\": 24,\n",
    "}\n",
    "cyclical_encoder = CyclicalFeatures(\n",
    "    variables     = features_to_encode,\n",
    "    max_values    = max_values,\n",
    "    drop_original = True\n",
    ")\n",
    "\n",
    "cyclical_features = cyclical_encoder.fit_transform(calendar_features)\n",
    "cyclical_features.head(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "bb6bf4d2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 350x300 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot value of sin and cos for each day_of_week\n",
    "# ==============================================================================\n",
    "fig, ax = plt.subplots(figsize=(3.5, 3))\n",
    "sp = ax.scatter(\n",
    "         cyclical_features[\"day_of_week_sin\"],\n",
    "         cyclical_features[\"day_of_week_cos\"],\n",
    "         c    = calendar_features['day_of_week'],\n",
    "         cmap = 'viridis'\n",
    "     )\n",
    "ax.set(\n",
    "    xlabel=\"sin(day_of_week)\",\n",
    "    ylabel=\"cos(day_of_week)\",\n",
    ")\n",
    "_ = fig.colorbar(sp)\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 350x300 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot value of sin and cos for each hour\n",
    "# ==============================================================================\n",
    "fig, ax = plt.subplots(figsize=(3.5, 3))\n",
    "sp = ax.scatter(\n",
    "         cyclical_features[\"hour_sin\"],\n",
    "         cyclical_features[\"hour_cos\"],\n",
    "         c    = calendar_features['hour'],\n",
    "         cmap = 'viridis'\n",
    "     )\n",
    "ax.set(\n",
    "    xlabel=\"sin(hour)\",\n",
    "    ylabel=\"cos(hour)\",\n",
    ")\n",
    "_ = fig.colorbar(sp)\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"admonition note\" name=\"html-admonition\" style=\"background: rgba(0,184,212,.1); padding-top: 0px; padding-bottom: 6px; border-radius: 8px; border-left: 8px solid #00b8d4; border-color: #00b8d4; padding-left: 10px; padding-right: 10px;\">\n",
    "\n",
    "<p class=\"title\">\n",
    "    <i style=\"font-size: 18px; color:#00b8d4;\"></i>\n",
    "    <b style=\"color: #00b8d4;\">&#9998 Note</b>\n",
    "</p>\n",
    "\n",
    "See <a href=\"../faq/cyclical-features-time-series.html\" target=\"_blank\">Cyclical features in time series forecasting</a> for a more detailed description of strategies for encoding cyclic features.\n",
    "\n",
    "</div>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "skforecast_py12",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
